package com.yy.permissions_general.module.system.aopLog.aspect;

import cn.hutool.core.util.URLUtil;
import cn.hutool.http.useragent.UserAgent;
import cn.hutool.http.useragent.UserAgentUtil;
import com.yy.permissions_general.module.system.aopLog.aop.MyLog;
import com.yy.permissions_general.module.system.aopLog.entity.SysLog;
import com.yy.permissions_general.module.system.aopLog.mapper.SysLogMapper;
import com.yy.permissions_general.utils.LogUtils;
import com.yy.permissions_general.utils.SecurityUtil;
import com.yy.permissions_general.utils.ServletUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Date;

/**
* @Description: 系统日志切面
* @Author: YY
* @Date: 2021/11/7
*/
@Component
@Aspect
@Slf4j
public class LogAspect {
    @Resource
    private SysLogMapper sysLogMapper;

    ThreadLocal<Long> currentTime = new ThreadLocal<>();
    /**
     * 设置操作日志切入点 记录操作日志 在注解的位置切入代码
     */
    @Pointcut("@annotation(com.yy.permissions_general.module.system.aopLog.aop.MyLog)")
    public void logPoinCut() {
    }

    /**
     * 配置环绕通知,使用在方法logPointcut()上注册的切入点
     *
     * @param joinPoint join point for advice
     */
    @Around("logPoinCut()")
    public Object saveSysLog(ProceedingJoinPoint joinPoint)throws Throwable{
        Object result;
        //记录方法的执行时间
        currentTime.set(System.currentTimeMillis());
        result = joinPoint.proceed();
        //定义日志类型
        SysLog sysLog = new SysLog();
        sysLog.setLogType("INFO");
        sysLog.setTaskType(2);
        sysLog.setStartTime(new Date(System.currentTimeMillis()));
        sysLog.setExecuteTime(System.currentTimeMillis() - currentTime.get());
        sysLog.setEndTime(new Date(currentTime.get()));
        currentTime.remove();
        HttpServletRequest request = ServletUtil.getRequest();
        sysLog.setCreateUserCode(SecurityUtil.getCurrentUser().getAccount());
        sysLog.setCreateUserName(SecurityUtil.getCurrentUser().getUsername());
        sysLog.setBrowserName(LogUtils.getBrowser(request));
        sysLog.setRequestIp(LogUtils.getIp(request));
        sysLog.setServerAddress(request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort());
        String userAgentStr = request.getHeader("User-Agent");
        UserAgent userAgent = UserAgentUtil.parse(userAgentStr);
        sysLog.setDeviceName(userAgent.getOs().getName());
        sysLog.setUserAgent(userAgentStr);
        sysLog.setRequestUrl(URLUtil.getPath(request.getRequestURI()));
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        MyLog myLog = method.getAnnotation(com.yy.permissions_general.module.system.aopLog.aop.MyLog.class);
        if (sysLog != null) {
            sysLog.setDescription(myLog.value());
        }
        sysLog.setIsException("0");
        method.getReturnType();
        sysLog.setRequestParams(LogUtils.formatParams(request.getParameterMap()));
        sysLog.setRequestMethod(request.getMethod());
        sysLog.setCreateDate(new Date());
        sysLogMapper.insert(sysLog);
        return result;
    }

    /**
     * 配置异常通知
     *
     * @param joinPoint join point for advice
     * @param e exception
     */
    @AfterThrowing(pointcut = "logPoinCut()", throwing = "e")
    public void logAfterThrowing(JoinPoint joinPoint, Throwable e) {
        SysLog sysLog = new SysLog();
        sysLog.setLogType("ERROR");
        sysLog.setTaskType(2);
        sysLog.setStartTime(new Date(System.currentTimeMillis()));
        sysLog.setExecuteTime(System.currentTimeMillis() - currentTime.get());
        sysLog.setEndTime(new Date(currentTime.get()));
        currentTime.remove();
        HttpServletRequest request = ServletUtil.getRequest();
        sysLog.setCreateUserCode(SecurityUtil.getCurrentUser().getAccount());
        sysLog.setCreateUserName(SecurityUtil.getCurrentUser().getUsername());
        sysLog.setBrowserName(LogUtils.getBrowser(request));
        sysLog.setRequestIp(LogUtils.getIp(request));
        sysLog.setServerAddress(request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort());
        String userAgentStr = request.getHeader("User-Agent");
        UserAgent userAgent = UserAgentUtil.parse(userAgentStr);
        sysLog.setDeviceName(userAgent.getOs().getName());
        sysLog.setUserAgent(userAgentStr);
        sysLog.setRequestUrl(URLUtil.getPath(request.getRequestURI()));
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        MyLog myLog = method.getAnnotation(com.yy.permissions_general.module.system.aopLog.aop.MyLog.class);
        if (sysLog != null) {
            sysLog.setDescription(myLog.value());
        }
        sysLog.setIsException("1");
        sysLog.setExceptionInfo(e.getMessage());
        sysLog.setRequestParams(LogUtils.formatParams(request.getParameterMap()));
        sysLog.setRequestMethod(request.getMethod());
        sysLog.setCreateDate(new Date());
        sysLogMapper.insert(sysLog);
    }
}
